package com.marveal.rabbit.api;

import com.marveal.rabbit.api.exception.MessageRuntimeException;
import com.marveal.rabbit.api.exception.MessageRuntimeExceptionType;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

/**
 * $MessageBuilder Message的建造者模式
 */
public class MessageBuilder implements Serializable {
    private String messageId;
    private String topic;
    private String routingKey;
    private Map<String, Object> attributes = new HashMap<>();
    private int delayMills;
    private MessageType messageType = MessageType.CONFIRM;

    private MessageBuilder() {}

    public static MessageBuilder create() {
        return new MessageBuilder();
    }

    public MessageBuilder withMessageId(String messageId) {
        this.messageId = messageId;
        return this;
    }

    public MessageBuilder withTopic(String topic) {
        this.topic = topic;
        return this;
    }

    public MessageBuilder withRoutingKey(String routingKey) {
        this.routingKey = routingKey;
        return this;
    }

    public MessageBuilder withAttributes(Map<String, Object> attributes) {
        this.attributes = attributes;
        return this;
    }

    public MessageBuilder withAttribute(String key, Object value) {
        this.attributes.put(key, value);
        return this;
    }

    public MessageBuilder withDelayMills(int delayMills) {
        this.delayMills = delayMills;
        return this;
    }

    public MessageBuilder withMessageType(MessageType messageType) {
        this.messageType = messageType;
        return this;
    }

    public Message build() {
        // check messageId is not empty
        // if messageID is empty , create a default uuid string
        if (Objects.isNull(messageId) || "".equals(messageId)) {
            this.messageId = UUID.randomUUID().toString().replace("-", "");
        }

        // check topic is not empty
        // if topic is empty , throw a runtime exception
        if (Objects.isNull(topic) || "".equals(topic)) {
            throw new MessageRuntimeException(MessageRuntimeExceptionType.MESSAGE_TOPIC_IS_EMPTY);
        }

        // check routingKey is not empty
        // if routingKey is empty , throw a runtime exception
        if (Objects.isNull(routingKey) || "".equals(routingKey)) {
            throw new MessageRuntimeException(MessageRuntimeExceptionType.MESSAGE_ROUTING_KEY_IS_EMPTY);
        }

        return new Message()
                .setMessageId(messageId)
                .setTopic(topic)
                .setRoutingKey(routingKey)
                .setAttributes(attributes)
                .setDelayMills(delayMills)
                .setMessageType(messageType);
    }

}
